package com.bjb.vr.auth.service;

import cn.hutool.core.codec.Base64;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.bjb.vr.auth.bo.UmsUserDetail;
import com.bjb.vr.auth.util.AccessRequestUtil;
import com.bjb.vr.common.ao.*;
import com.bjb.vr.common.constant.Constants;
import com.bjb.vr.common.constant.RoleConstants;
import com.bjb.vr.common.constant.ThreadLocalConstant;
import com.bjb.vr.common.constant.TokenConstants;
import com.bjb.vr.common.dto.UmsOptAccount;
import com.bjb.vr.common.dto.UmsOptRole;
import com.bjb.vr.common.dto.UmsOptRoleMenu;
import com.bjb.vr.common.dto.UmsOptUserRole;
import com.bjb.vr.common.mapper.UmsOptAccountMapper;
import com.bjb.vr.common.mapper.UmsOptRoleMapper;
import com.bjb.vr.common.mapper.UmsOptRoleMenuMapper;
import com.bjb.vr.common.mapper.UmsOptUserRoleMapper;
import com.bjb.vr.common.result.BaseResult;
import com.bjb.vr.common.result.CommonResult;
import com.bjb.vr.common.utils.JwtTokenUtil;
import com.bjb.vr.common.utils.ThreadLocalUtil;
import com.bjb.vr.common.vo.UmsRoleVo;
import io.jsonwebtoken.Claims;
import org.apache.commons.lang3.StringUtils;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.crypto.factory.PasswordEncoderFactories;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.Arrays;
import java.util.List;
import java.util.Objects;
import java.util.concurrent.atomic.AtomicBoolean;

/**
 * @description:
 * @author: HuJingBo
 * @time: 2022/11/17 11:27
 */
@Service
public class UmsOptAccountEnhanceService extends ServiceImpl<UmsOptAccountMapper, UmsOptAccount> {

    private PasswordEncoder passwordEncoder = PasswordEncoderFactories.createDelegatingPasswordEncoder();

    @Resource
    private AuthenticationManager authenticationManager;

    @Resource
    private UmsOptUserRoleMapper optUserRoleMapper;

    @Resource
    private UmsOptAccountMapper optAccountMapper;

    @Resource
    private UmsOptRoleMapper optRoleMapper;

    @Resource
    private UmsOptRoleMenuMapper optRoleMenuMapper;


    /**
     * 更新用户角色
     *
     * @param umsAccountAo
     */
    public boolean updateUserInfo(UmsAccountAo umsAccountAo) {
        ThreadLocalUtil.set(ThreadLocalConstant.NO_TENANT_ID_VERIFY, true);
        UmsOptAccount optAccount = new UmsOptAccount();
        optAccount.setUserId(umsAccountAo.getUserId());
        // 更新用户角色信息
        if (umsAccountAo.getRoleId() != null) {
            UmsOptUserRole optUserRole = new UmsOptUserRole();
            optUserRole.setUserId(umsAccountAo.getUserId());
            optUserRole.setRoleId(umsAccountAo.getRoleId());
            // 判断是否为空:为空新增，否则更新
            UmsOptUserRole umsOptUserRole = optUserRoleMapper.selectOne(new LambdaQueryWrapper<UmsOptUserRole>().eq(UmsOptUserRole::getUserId, umsAccountAo.getUserId()));
            if (Objects.isNull(umsOptUserRole)) {
                optUserRoleMapper.insert(optUserRole);
            } else {
                optUserRoleMapper.update(optUserRole, new LambdaQueryWrapper<UmsOptUserRole>().eq(UmsOptUserRole::getUserId, umsAccountAo.getUserId()));
            }
        }
        // 更新用户信息
        return this.updateById(optAccount);
    }

    /**
     * 校验用户名密码是否正确
     *
     * @param authorization
     * @param accountResetPwdAo
     * @return
     */
    public BaseResult verifyUserNameAndPassword(String authorization, UmsAccountResetPwdAo accountResetPwdAo) {
        // 认证用户名密码
        Claims claims = JwtTokenUtil.parseJWT(authorization);
        String username = String.valueOf(claims.get(TokenConstants.TOKEN_USERNAME));
        String loginType = String.valueOf(claims.get(TokenConstants.LOGIN_TYPE));
        try {
            Authentication authenticate = authenticationManager.authenticate(new UsernamePasswordAuthenticationToken(username, accountResetPwdAo.getOldPassword()));
            boolean authenticated = authenticate.isAuthenticated();
            if (authenticated) {
                UmsUserDetail principal = (UmsUserDetail) authenticate.getPrincipal();
                UmsAccountPwdAo umsAccountPwdAo = new UmsAccountPwdAo();
                umsAccountPwdAo.setId(principal.getUserId());
                umsAccountPwdAo.setPassword(accountResetPwdAo.getNewPassword());
                umsAccountPwdAo.setLoginType(loginType);
                return CommonResult.Ok().setResult(umsAccountPwdAo);
            }
            return CommonResult.Fail("旧密码错误,认证失败！");
        } catch (Exception e) {
            return CommonResult.Fail("旧密码错误,认证失败！");
        }
    }

    /**
     * 更新用户密码
     *
     * @param accountPwdAo
     * @return
     */
    public boolean updateOptUserPassword(UmsAccountPwdAo accountPwdAo) {
        ThreadLocalUtil.set(ThreadLocalConstant.NO_TENANT_ID_VERIFY, true);
        try {
            UmsOptAccount umsOptAccount = new UmsOptAccount();
            umsOptAccount.setId(accountPwdAo.getId());
            umsOptAccount.setInitialPass(Constants.NO);
            if (StringUtils.isNotBlank(accountPwdAo.getPassword())) {
                umsOptAccount.setPassword(passwordEncoder.encode(Base64.decodeStr(accountPwdAo.getPassword())));
            }
            return optAccountMapper.updateById(umsOptAccount) == 1;
        } catch (Exception e) {
            log.error(e.getMessage());
            return false;
        }
    }

    /**
     * 更新用户状态
     *
     * @param statusAo
     * @return
     */
    public boolean updateUserStatus(UmsAccountStatusAo statusAo) {
        ThreadLocalUtil.set(ThreadLocalConstant.NO_TENANT_ID_VERIFY, true);
        UmsOptAccount optAccount = new UmsOptAccount();
        optAccount.setId(statusAo.getId());
        optAccount.setStatus(statusAo.getStatus());
        // 更新用户密码
        return this.updateById(optAccount);
    }

    /**
     * 查询角色信息--列表
     *
     * @param userRoleAo
     */
    public List<UmsRoleVo> queryRoleInfo(UmsUserRoleAo userRoleAo) {
        ThreadLocalUtil.set(ThreadLocalConstant.NO_TENANT_ID_VERIFY, true);
        List<UmsRoleVo> roleVos = optRoleMapper.queryRoleInfosByCondition(userRoleAo);
        return roleVos;
    }

    /**
     * 查询角色信息--单条
     *
     * @param roleName
     */
    public UmsOptRole queryRoleByName(String roleName) {
        ThreadLocalUtil.set(ThreadLocalConstant.NO_TENANT_ID_VERIFY, true);
        UmsOptRole umsOptRole = optRoleMapper.selectOne(new LambdaQueryWrapper<UmsOptRole>().eq(StringUtils.isNotBlank(roleName), UmsOptRole::getRoleName, roleName));
        return umsOptRole;
    }

    /**
     * 新增角色
     *
     * @param umsRoleAo
     * @return
     */
    @Transactional(rollbackFor = Exception.class)
    public boolean addRoleInfo(UmsRoleAo umsRoleAo) {
        AtomicBoolean result = new AtomicBoolean(true);
        // 新增角色
        String username = AccessRequestUtil.getUserName();
        UmsOptRole optRole = new UmsOptRole();
        optRole.setRoleName(umsRoleAo.getRoleName());
        optRole.setRemark(umsRoleAo.getRoleName());
        optRole.setCreateBy(username);
        if (StringUtils.isBlank(umsRoleAo.getRoleKey())) {
            optRole.setRoleKey(RoleConstants.COMMON);
        }
        optRoleMapper.insert(optRole);

        // 关联角色和权限
        Arrays.stream(umsRoleAo.getMenuIds()).forEach(m -> {
            try {
                UmsOptRoleMenu optRoleMenu = new UmsOptRoleMenu();
                optRoleMenu.setRoleId(optRole.getRoleId());
                optRoleMenu.setMenuId(m);
                optRoleMenu.setType(umsRoleAo.getType());
                optRoleMenuMapper.insert(optRoleMenu);
            } catch (Exception e) {
                result.set(false);
                log.error(e.getMessage());
            }
        });
        return result.get();
    }

    /**
     * 编辑角色
     *
     * @param umsRoleAo
     * @return
     */
    public boolean updateRole(UmsRoleAo umsRoleAo) {
        AtomicBoolean result = new AtomicBoolean(true);
        // 修改角色
        String username = AccessRequestUtil.getUserName();
        UmsOptRole optRole = new UmsOptRole();
        optRole.setId(umsRoleAo.getId());
        optRole.setRoleName(umsRoleAo.getRoleName());
        optRole.setRemark(umsRoleAo.getRoleName());
        optRole.setStatus(umsRoleAo.getStatus());
        optRole.setUpdateBy(username);
        optRoleMapper.updateById(optRole);

        if (Objects.isNull(umsRoleAo.getMenuIds())) {
            result.set(true);
            return result.get();
        }

        LambdaQueryWrapper<UmsOptRoleMenu> deleteWrapper = new LambdaQueryWrapper<>();
        deleteWrapper.eq(UmsOptRoleMenu::getRoleId, umsRoleAo.getRoleId());
        optRoleMenuMapper.delete(deleteWrapper);
        // 关联角色和权限
        Arrays.stream(umsRoleAo.getMenuIds()).forEach(m -> {
            try {
                UmsOptRoleMenu optRoleMenu = new UmsOptRoleMenu();
                optRoleMenu.setRoleId(umsRoleAo.getRoleId());
                optRoleMenu.setMenuId(m);
                optRoleMenu.setType(umsRoleAo.getType());
                optRoleMenuMapper.insert(optRoleMenu);
            } catch (Exception e) {
                result.set(false);
                log.error(e.getMessage());
            }
        });
        return result.get();
    }
}
